#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <stdint.h>

#define LOCAL_IP     "192.168.2.76"
#define LOCAL_PORT   9000
#define BUF_SIZE     1024


typedef struct {
    uint8_t  TID;       // TID_MVB_PD_DATA
    uint8_t  fcode;     // 端口字节大小 0,1,2,3,4
    uint16_t pdPort;    // 端口号
    uint8_t  pdData[32];// 数据区
} mvb_data_full;

#define MVB_HEADER_0 0x21
#define MVB_HEADER_1 0x04
#define HEADER_SIZE  (sizeof(uint8_t) * 2)           // TID + fcode
#define ADDR_SIZE    (sizeof(uint16_t))              // pdPort
#define LEN_SIZE     (sizeof(mvb_data_full))         // 整个数据结构长度
#define CRC_SIZE     (sizeof(uint16_t))              // 假设CRC为2字节



//此函数根据不同的端口， 映射不同的数据结构， 并得到的列车参数内容
void port_action(uint16_t pdPort_be, uint8_t *data)
{
    switch (pdPort_be) {
        case 0x00F9:
            printf("pdPort_be = 【车载重量】\n");
            break;
        default:
            printf("pdPort_be = %d\n", pdPort_be);
    }·
}


int main() {
    int sockfd;
    struct sockaddr_in localaddr, remoteaddr;
    char buffer[BUF_SIZE];
    socklen_t addr_len = sizeof(remoteaddr);
    ssize_t n;

    // 创建UDP套接字
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

    memset(&localaddr, 0, sizeof(localaddr));
    localaddr.sin_family = AF_INET;
    localaddr.sin_addr.s_addr = inet_addr(LOCAL_IP);
    localaddr.sin_port = htons(LOCAL_PORT);
    if (bind(sockfd, (struct sockaddr*)&localaddr, sizeof(localaddr)) < 0) {
        perror("bind error");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    printf("等待接收MVB协议UDP数据...\n");
    while (1) {
    
        n = recvfrom(sockfd, buffer, BUF_SIZE, 0, (struct sockaddr*)&remoteaddr, &addr_len);
        if (n < 0) {
            perror("recvfrom error");
            break;
        }
        // printf("收到数据(%zd字节): ", n);
        // for (ssize_t i = 0; i < n; ++i) {
        //     printf("%02X ", (unsigned char)buffer[i]);
        // }

        // 将接收到的数据映射为 mvb_data_full 结构体
        printf("mvb_data_full 结构体大小: %zu\n", sizeof(mvb_data_full));
        
        // mvb_data_full *mvb_data = (mvb_data_full *)buffer;

        mvb_data_full mvb_data_zero = {0};
        memcpy(&mvb_data_zero, buffer, sizeof(mvb_data_full));
        mvb_data_full *mvb_data = &mvb_data_zero;

         for (ssize_t i = 0; i < sizeof(mvb_data_full); ++i) {
            printf("%02X ", (unsigned char)buffer[i]);
        }
        
        // 你可以在这里访问 mvb_data 的各个字段，例如:
        // 修正：假设 mvb_data_full 结构体中 pdPort 字段不是 header 指针下的成员，而是直接成员
        // 正确输出 pdPort 的数值，假设 pdPort 是 uint16_t 类型，避免类型提升导致的错误

        uint16_t pdPort_be = ((uint8_t*)&mvb_data->pdPort)[0] << 8 | ((uint8_t*)&mvb_data->pdPort)[1];

        printf("mvb_data->pdPort (10进制) = %d\n", pdPort_be);
    
        printf("mvb_data->pdPort (十六进制): ");
        // 假设 pdPort 是一个非数组类型（如 uint16_t 或 uint32_t），逐字节打印
        char pdPort_hex[sizeof(mvb_data->pdPort) * 2 + 1] = {0};
        for (size_t i = 0; i < sizeof(mvb_data->pdPort); ++i) {
            sprintf(&pdPort_hex[i * 2], "%02X", ((unsigned char*)&mvb_data->pdPort)[i]);
        }
        printf("%s\n", pdPort_hex);
        
        // 优化switch：用结构体数组映射pdPort_be到描述，查找更高效，便于维护
        typedef struct {
            uint16_t port;
            const char *desc;
        } PdPortDesc;

        static const PdPortDesc pdPortDescTable[] = {
            {0x00F9, "【车载重量】"},
            {0x00FF, "【时钟】"},
            {0x0027, "【空调能耗】"},
            {0x0191, "【列车温湿度数据】"},
            {0x0291, "【列车温湿度数据】"},
            {0x0391, "【列车温湿度数据】"},
            {0x0491, "【列车温湿度数据】"},
            {0x0190, "【列车数据】"},
            {0x0290, "【列车数据】"},
            {0x0390, "【列车数据】"},
            {0x0490, "【列车数据】"},
        };

        const char *desc = NULL;
        for (size_t i = 0; i < sizeof(pdPortDescTable)/sizeof(pdPortDescTable[0]); ++i) {
            if (pdPort_be == pdPortDescTable[i].port) {
                desc = pdPortDescTable[i].desc;
                
                //执行端口数据处理动作
                port_action(pdPort_be, mvb_data->pdData);
                break;
            }
        }

        if (desc) {
            printf("pdPort_be = %s\n", desc);
        } else {
            printf("pdPort_be = %d\n", pdPort_be);
        }

        //读取的到数据 映射到 中心数据集合 ，条件当前的情况组合

            //持续时长
            //温度条件
            //湿度条件
            //重量条件
            //是否紧急模式
            //空调能耗条件
            //列车数据条件
            //列车温湿度数据条件
            //列车数据条件

        //异步脚本来试试
            //存储到同一个内存区块
            //异步数据调整，流数据处理更新
            //工况温判定
            //工况指令下发

        
        //数据封装下发，下发到低碳节能平台， 平台下发到设备
            //上行发送数据
            //下行存储数据 状态判定


      
        printf("\n");

        //端口重置 
        pdPort_be   = 0x0000;
        //释放buffer 空间后续使用
        memset(buffer, 0, sizeof(buffer));
    }
    close(sockfd);
    
    return 0;
}







